package io.jsen.meta.diff.context;

import com.google.common.reflect.TypeToken;
import io.jsen.meta.diff.IMetaContext;
import io.jsen.meta.diff.feature.parser.MetaFieldConfigInject;
import io.jsen.meta.diff.obj.Convert;
import io.jsen.meta.diff.obj.MetaObject;
import io.jsen.meta.diff.support.MetaDiffModel;

/**
 * @author jsen
 * @date 2021/09/18
 **/
public class DefaultMetaContext implements IMetaContext {
    public static IMetaContext instance = new DefaultMetaContext();

    static {
        DefaultMetaConvertInit.register();
    }

    @Override
    public void loadDefine(String path) {
        MetaFieldConfigInject.registerJsonConfig(path);
    }

    @Override
    @SuppressWarnings("all")
    public <T> void loadDefine(TypeToken<T> typeToken) {
        MetaFieldDefineContext.register(typeToken);
    }

    @Override
    @SuppressWarnings("all")
    public <T> MetaObject<?, ?> diffMeta(TypeToken<T> typeToken, T newObj, T oldObj) {
        loadDefine(typeToken);
        MetaDiffModel<T> diffModel = new MetaDiffModel<>(typeToken, newObj, oldObj);
        return MetaOpContext.toMeta(diffModel);
    }

    @Override
    @SuppressWarnings("all")
    public <T> MetaObject<?, ?> toMeta(TypeToken<T> typeToken, T nativeObj) {
        loadDefine(typeToken);
        return MetaOpContext.loadMeta(typeToken, nativeObj);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T toNative(MetaObject<?, ?> metaObject) {
        return (T) MetaOpContext.toNative(metaObject);
    }

    @Override
    public <S, T> void registerConvert(Class<?> clazz, Convert<S, T> convert) {
        MetaObjectConvertContext.register(clazz, convert);
    }
}
